package lee.study.utils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.SocketException;


/**
 * @author licc
 * @create 2018-01-10 14:32
 * @desc 基于FTP的读写
 **/
@SuppressWarnings("all")
public class FTPUtils {
    private String ftpUsername;
    private String ftpPassword;
    private String ftpHost;
    private String ftpPort;

    public String getFtpUsername() {
        return ftpUsername;
    }

    public void setFtpUsername(String ftpUsername) {
        this.ftpUsername = ftpUsername;
    }

    public String getFtpPassword() {
        return ftpPassword;
    }

    public void setFtpPassword(String ftpPassword) {
        this.ftpPassword = ftpPassword;
    }

    public String getFtpHost() {
        return ftpHost;
    }

    public void setFtpHost(String ftpHost) {
        this.ftpHost = ftpHost;
    }

    public String getFtpPort() {
        return ftpPort;
    }

    public void setFtpPort(String ftpPort) {
        this.ftpPort = ftpPort;
    }

    private static final Logger logger = LoggerFactory.getLogger(FTPUtils.class);

    public FTPUtils() {
    }

    public FTPUtils(String ftpUsername, String ftpPassword, String ftpHost, String ftpPort) {
        this.ftpUsername = ftpUsername;
        this.ftpPassword = ftpPassword;
        this.ftpHost = ftpHost;
        this.ftpPort = ftpPort;
    }

    public static FTPUtils getInstance(String ftpUsername, String ftpPassword, String ftpHost, String ftpPort){
        FTPUtils ftpUtils = new FTPUtils(ftpUsername,ftpPassword,ftpHost,ftpPort);
        return ftpUtils;
    }


    /**
     * Description: 从FTP服务器下载文件
     *
     * @param remotePath FTP服务器上的相对路径
     * @param fileName   要下载的文件名
     * @param localPath  下载后保存到本地的路径
     * @return
     */
    public boolean downFile(/*String remotePath, */String fileName, OutputStream os,FTPUtils ftpUtils) throws IOException {
        boolean success = false;
        FTPClient ftp = getFTPClient(ftpUtils);
        try {
            int reply;
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return success;
            }

            //转移到FTP服务器目录
//            ftp.changeWorkingDirectory(remotePath);
            FTPFile[] fs = ftp.listFiles();
            for (FTPFile ff : fs) {
                if (ff.getName().equals(fileName)) {
                    ftp.enterLocalPassiveMode();
                    ftp.retrieveFile(ff.getName(), os);
                    os.close();
                }
            }
            ftp.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭FTP连接
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }


    /**
     * Description: 向FTP服务器上传文件
     *
     * @param path     FTP服务器保存目录 如:"G:\\ftp_test\\"
     * @param filename 上传到FTP服务器上的文件名
     * @param input    输入流
     * @return 成功返回true，否则返回false
     * @Version1.0 Jul 27, 2008 4:31:09 PM by 崔红保（cuihongbao@d-heaven.com）创建
     */
    public boolean uploadFile(String filename, InputStream input,FTPUtils ftpUtils) throws IOException {
        boolean success = false;
        FTPClient ftp = getFTPClient(ftpUtils);
        try {
            int reply;
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return success;
            }

            filename = new String(filename.getBytes("GBK"),"ISO8859-1");
            FTPFile[] fs = ftp.listFiles();
            for (FTPFile ff : fs){
                if (ff.getName().equals(filename)) {
                    System.out.println("该文件已存在!");
                    return false;
                }
            }

            /**
             * 设置上传类型
             * 默认使用的是ASCII编码的。如果是二进制文件,则要设置文件类型。
             */
            boolean result = ftp.setFileType(ftp.LOCAL_FILE_TYPE);
//            ftp.changeWorkingDirectory("/");



//            ftp.changeWorkingDirectory("/a/");
            /**
             * 上传文件
             * fileName为上传到服务器的文件名
             *
             * 文件可能会被覆盖,有待确定
             *
             * 还有一个问题，就是这个方法可能会存在阻塞状态。跟踪源文件后，才发现这个方法里面
             * 使用了socket，默认端口是0，如果服务器上设置了端口限制的话，就会因为端口没开导致阻塞状态。
             *
             * FTPClient还有一个方法，就是storeUniqueFile方法，存储为唯一的文件名，即如果服务器存在这个文件
             * 那么该文件会在文件名后面加1、2、3、4的。比如，我要上传1.jpg。但是是服务器上存在这个文件，那么
             * 它会将1.jpg改成11.jpg，如果11.jpg还存在，就改为12.jpg，以此类推13.jpg... 直到服务器不存在为止。
             * 但是使用这个有个问题，就是我不知道服务器最终存入的文件名是什么。
             */
//            ftp.enterLocalPassiveMode();
            success = ftp.storeFile(filename, input);

            input.close();
            ftp.logout();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }

    /**
     * 获取FTPClient对象
     *
     * @return
     */
    public FTPClient getFTPClient(FTPUtils ftpUtils) throws IOException {

//        //FTP登录用户名
//        String ftpUserName = "admin";
//        //FTP登录密码
//        String ftpPassword = "admin";
//        //FTP主机服务器
//        String ftpHost = "172.16.103.189";
//        //FTP端口 默认为21
//        Integer ftpPort = 21;


//        //读取配置文件
//        InputStream in = FTPUtils.class.getClassLoader()
//                .getResourceAsStream("application.properties");
//        if (in == null) {
//            logger.info("配置文件application.properties读取失败");
//        } else {
//            Properties properties = new Properties();
//            properties.load(in);
//            ftpUserName = properties.getProperty("ftp.username");
//            ftpPassword = properties.getProperty("ftp.password");
//            ftpHost = properties.getProperty("ftp.host");
//            ftpPort = Integer.parseInt(properties.getProperty("ftp.port"));
//        }


        //连接FTP服务器并登陆
        FTPClient ftpClient = null;
        try {
            ftpClient = new FTPClient();
            ftpClient.connect(ftpUtils.getFtpHost(), Integer.parseInt(ftpUtils.getFtpPort()));// 连接FTP服务器
            ftpClient.login(ftpUtils.getFtpUsername(), this.getFtpPassword());// 登陆FTP服务器
            ftpClient.enterLocalPassiveMode();
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                logger.info("未连接到FTP，用户名或密码错误。");
                ftpClient.disconnect();
            } else {
                logger.info("FTP连接成功。");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            logger.info("FTP的IP地址可能错误，请正确配置。");
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("FTP的端口错误,请正确配置。");
        }
        return ftpClient;
    }



    /**
     * 删除单个文件
     *
     * @param fileName
     *            要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功！");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败！");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败：" + fileName + "不存在！");
            return false;
        }
    }

    public static void main(String[] args) throws IOException {
        //FTP登录用户名
        String ftpUserName = "admin";
        //FTP登录密码
        String ftpPassword = "admin";
        //FTP主机服务器
        String ftpHost = "172.16.103.189";
        //FTP端口 默认为21
        String ftpPort = "21";
        File file = new File("G:\\ftp_write\\timina.mp3");
        FTPUtils ftpUtils = FTPUtils.getInstance(ftpUserName,ftpPassword,ftpHost,ftpPort);
        ftpUtils.downFile( "timina.mp3", new FileOutputStream(file),ftpUtils);


    }
}
